import { Handler } from "$fresh/server.ts";
import {
  CredentialMeta,
  GetCredit,
  UpdateCredential,
} from "~/denokv/resume.ts";
import { getResumeAuthingSDK } from "~/tools/sdk/authing.ts";
import { getCookies } from "$std/http/cookie.ts";
import dayjs from "dayjs";
import { setCookie } from "$std/http/mod.ts";
import { ConsoleHandler, getLogger, setup } from "logger";
import { UserInfo } from "~/types.ts";
setup({
  handlers: {
    default: new ConsoleHandler("INFO", {
      formatter: (record) => {
        return `resume middleware: ${
          dayjs(record.datetime).format("YYYY-MM-DD HH:mm:ss")
        } [${record.levelName}] ${record.msg}`;
      },
    }),
  },
});
const dl = getLogger();
export interface ResumeCTX extends CredentialMeta {
  st: string;
  userInfo: UserInfo;
}
export const DriverIDKey = "di";
export const handler: Handler<
  unknown,
  ResumeCTX
> = async (req, ctx) => {
  if (req.method === "POST" && ctx.url.pathname === "/resume") {
    dl.warn(`${ctx.url.pathname}接收到新的认证凭据,忽略剩下逻辑`);
    return ctx.next();
  }
  const { searchParams } = ctx.url;
  // const accessToken = searchParams.get("ac") as string;
  const state = searchParams.get("st") as string;
  if (!state) {
    dl.info("没有st");
    return new Response(null, {
      status: 302,
      headers: {
        Location: `/`,
      },
    });
  }

  const result = await GetCredit(state);
  if (!result || !result.accessToken) {
    dl.info("没有查询到缓存");

    return new Response(null, {
      status: 302,
      headers: {
        Location: `/`,
      },
    });
  }
  dl.info("通过state:" + state + "查询到分享凭据");
  const sdk = getResumeAuthingSDK();
  const { active } = await sdk.introspectToken(result.accessToken);

  if (!active) {
    dl.info("用户actoken已失效:" + state);
    return new Response(null, {
      status: 302,
      headers: {
        Location: `/`,
      },
    });
  }
  dl.info("state:" + state + ":有效");

  const userInfo: UserInfo = await sdk.getUserInfoByAccessToken(
    result.accessToken,
  );

  if (!userInfo) {
    dl.info("没有根据ac查询到用户信息:" + result.accessToken);
    return new Response(null, {
      status: 302,
      headers: {
        Location: `/`,
      },
    });
  }
  dl.info("state:" + state + ":获得用户openid:" + userInfo.sub);
  dl.info("state:" + state + ":获得用户openid:" + userInfo.sub);
  ctx.state = { ...result, st: state, userInfo };
  const cookies = getCookies(req.headers);
  const resp = await ctx.next();
  // 如果没有设备id,则创建一个访问设备id
  if (!cookies[DriverIDKey]) {
    const uuid = crypto.randomUUID();
    dl.info("发现新访问设备,标记id: " + uuid);
    result.drives.push({
      createAt: dayjs().format("YYYY-MM-DD HH:mm:ss"),
      driveId: uuid,
    });
    setCookie(resp.headers, {
      name: DriverIDKey,
      value: uuid,
      path: "/resume",
      maxAge: result.duration -
        dayjs().diff(dayjs(result.createAt), "second"),
      httpOnly: true,
    });
    const { ok } = await UpdateCredential(result);
    if (!ok) {
      dl.warn("更新设备id失败");
    }
  } else {
    dl.info("state:" + state + ":访问设备:" + cookies[DriverIDKey]);
    // todo 什么设备什么时候访问过可以在此记录
  }

  return resp;
};
